var post_url = "http://www.mermexico.com/dpm/projects/hangman/hangman.php";
var preferences_url = "http://www.mermexico.com/dpm/projects/hangman/preferences.php";

function or () {
 for (var i=0; i<or.arguments.length; i++) if (typeof(or.arguments[i]) != "undefined") return or.arguments[i];
 return null;
}

function createDiv( /* [_id], [_firstChild] */ ) {
 var temp_div = document.createElement("DIV");
 if (typeof(arguments[0]) == 'string') temp_div.id = arguments[0];
 if (typeof(arguments[1]) == 'object') temp_div.appendChild(arguments[1]);
 return temp_div;
}

var Notify = {};

Notify.init = function () {
 this.messages = [];
 this.log = [];
 this.notediv = document.createElement("DIV");
 this.notediv.id = "notify_div";
 document.getElementById("body").appendChild(this.notediv);
 window.setInterval("Notify.update();", 500);
};

Notify.addMessage = function ( _message /* , [ _maxage ] */ ) {
 var maxage = 6000;
 if (typeof(arguments[1]) == "number") maxage = arguments[1];
 this.messages[this.messages.length] = { "message" : _message, "timestamp" : Date.now(), "maxage" : maxage };
 this.render();
};

Notify.render = function () {
 if (this.messages.length) {
  this.notediv.style.top = or(window.scrollY, window.pageYOffset, document.body.scrollTop) + 10;
  this.notediv.style.left = or(window.innerWidth, document.body.offsetWidth) - 250;
  this.notediv.innerHTML = "";
  for (var i in this.messages) this.notediv.innerHTML += this.messages[i].message + '<br/>';
  this.notediv.style.display = "block";
 } else {
  this.notediv.innerHTML = "";
  this.notediv.style.display = "none";
 }
};

Notify.update = function () {
  Notify.render();
  var temp_messages = [];
  for (var i in this.messages) {
   var age = Date.now() - this.messages[i].timestamp;
   if (this.messages[i].maxage == 0) temp_messages[temp_messages.length] = this.messages[i];
   else if (this.messages[i].maxage > age) temp_messages[temp_messages.length] = this.messages[i];
  }
  this.messages = temp_messages;
};

var XHR = {};

XHR.getXHRObject = function () {
 if (window.XMLHttpRequest) {
  return new XMLHttpRequest;
 } else if (window.ActiveXObject) {
  return new ActiveXObject("Microsoft.XMLHTTP");
 } else {
  return null;
 }
};

XHR.sendRequest = function ( _cmd, _payload, _callback ) {
 var xreq = XHR.getXHRObject();
 if (!xreq) { return; }
 xreq.open("POST", post_url, true);
 var poststring = "";
 poststring += "cmd=ajaxrequest";
 poststring += "&ajaxcmd=" + escape(_cmd);
 for (var i in _payload) poststring += "&" + escape(i) + "=" + escape(_payload[i]);
 xreq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
 xreq.onreadystatechange = function () {
  if (xreq.readyState == 4) {
   if (xreq.status == 200) _callback( eval("(" + xreq.responseText + ")") );
   else _callback(null);
  }
 };
 xreq.send(poststring);
};


XHR.getNewPuzzle = function ( ) {
 Notify.addMessage("Fetching new puzzle from server...");
 XHR.sendRequest(
  "getNewPuzzle",
  {},
  function ( _response ) {
   if (_response && _response.exitMessage) Notify.addMessage(_response.exitMessage);
   if (!_response || _response.exitCode) return; 
   if (_response.id &&_response.lang1 && _response.lang2) Puzzle.setPuzzle(_response.id, _response.lang1, _response.lang2); 
   else return;
  }
 );
};

XHR.updateScore = function ( _puzzle_id, _score ) {
 Notify.addMessage("Update score on server...");
 XHR.sendRequest(
  "updateScore",
  { 'puzzle_id' : _puzzle_id, 'score' : _score },
  function ( _response ) {
   if (_response && _response.exitMessage) Notify.addMessage(_response.exitMessage);
   if (!_response || _response.exitCode) return; 
  }
 );
};

var PuzzleImage = {};

PuzzleImage.init = function () {
 this.image_urls = [ 
  'images/stage0.gif',
  'images/stage1.gif',
  'images/stage2.gif',
  'images/stage3.gif',
  'images/stage4.gif',
  'images/stage5.gif',
  'images/stage6.gif'
 ];
 this.image_element = document.createElement("IMG");
 this.setStage(0);
};

PuzzleImage.getImageElement = function () {
 return this.image_element;
};

PuzzleImage.setStage = function ( _stage ) {
 this.stage = _stage;
 if (this.stage < this.image_urls.length) {
  this.image_element.src = this.image_urls[this.stage];
 } else {
  this.image_element.src = this.image_urls[this.image_urls.length-1];
 }
};


var Guesses = {};

Guesses.init = function () {
 this.guesses = [];
 this.guesses_element = document.createElement("SPAN");
};

Guesses.addGuess = function ( _guess ) {
 this.guesses[this.guesses.length] = _guess;
 this.guesses_element.innerHTML = this.guesses.join(' ');
};

Guesses.getGuessesElement = function () {
 return this.guesses_element;
};

Guesses.getGuessesRegExp = function () {
 // for use by WordMask -- to replace every alphabet character not already guessed 
 var alphabet_string = Alphabet.join('');
 alphabet_string = alphabet_string.replace(new RegExp('[' + this.guesses.join('') + ']', 'gi'), '');
 return new RegExp( ('[' + alphabet_string + ']') , 'gi');
};



var WordMask = {};

WordMask.init = function () {
 this.wordmask_element = document.createElement("SPAN");
};

WordMask.getWordMask = function () {
 var guessed_regex = Guesses.getGuessesRegExp(); 
 return Puzzle.getLang2().replace(guessed_regex, '_');
};

WordMask.getWordMaskElement = function () {
 return this.wordmask_element;
};

WordMask.updateWordMask = function () {
 this.wordmask_element.innerHTML = this.getWordMask();
};


var Hint = {};

Hint.init = function () {
 this.hint = '';
 this.hint_element = document.createElement("SPAN");
 this.setHint(this.hint);
};

Hint.getHintElement = function () {
 return this.hint_element;
};

Hint.setHint = function ( _hint ) {
 this.hint = _hint;
 this.hint_element.innerHTML = this.hint;
};


var GuessLinks = {};

GuessLinks.init = function () {
 this.guesslinks_element = document.createElement("SPAN");

 for (var i in Alphabet) {
  var guesslink = document.createElement("A");
  guesslink.innerHTML = Alphabet[i] + ' ';  // figure out how to fix this with css later
  guesslink.guesscharacter = Alphabet[i];
  guesslink.href = '';
  guesslink.onclick = function () {
   Puzzle.makeGuess(this.guesscharacter);
   GuessLinks.removeGuessLink(this);
   return false;
  };
  GuessLinks.addGuessLink(guesslink);
 }

};

GuessLinks.getGuessLinksElement = function () {
 return this.guesslinks_element;
};

GuessLinks.addGuessLink = function ( _guesslink ) {
 this.guesslinks_element.appendChild( _guesslink );
};

GuessLinks.removeGuessLink = function ( _guesslink ) {
 this.guesslinks_element.removeChild( _guesslink );
};


var Puzzle = {};

Puzzle.init = function () {

 this.puzzleid = 0; // puzzle id for DB

 this.lang1 = ''; // native language word
 this.lang2 = ''; // foreign language word

 this.hits = 0; // number of correct guesses
 this.misses = 0; // number of incorrect guesses

 PuzzleImage.init();
 Guesses.init();
 WordMask.init();
 Hint.init();
 GuessLinks.init();

 Puzzle.draw();

};

Puzzle.getLang1 = function () {
 return this.lang1;
};

Puzzle.getLang2 = function () {
 return this.lang2;
};

Puzzle.draw = function () {

 this.puzzle_container = createDiv("puzzle_container"); 

 this.puzzle_container.appendChild(createDiv("image_container", PuzzleImage.getImageElement()));
 this.puzzle_container.appendChild(createDiv("wordmask_container", WordMask.getWordMaskElement()));
 this.puzzle_container.appendChild(createDiv("guessed_container", Guesses.getGuessesElement()));
 this.puzzle_container.appendChild(createDiv("guesslinks_container", GuessLinks.getGuessLinksElement()));
 this.puzzle_container.appendChild(createDiv("hint_container", Hint.getHintElement()));

 var command_container = createDiv("command_container");

 var new_puzzle_button = document.createElement('BUTTON');
 new_puzzle_button.onclick = XHR.getNewPuzzle;
 new_puzzle_button.innerHTML = 'Get New Puzzle';

 var preferences_button = document.createElement('BUTTON');
 preferences_button.onclick = function () { window.location.href = preferences_url; }
 preferences_button.innerHTML = 'Edit Preferences';

 command_container.appendChild(new_puzzle_button);
 command_container.appendChild(preferences_button);

 this.puzzle_container.appendChild(command_container);

 var old_container = document.getElementById('puzzle_container');
 if (old_container) {
  document.getElementById("container").replaceChild(this.puzzle_container, old_container);
 } else {
  document.getElementById("container").appendChild(this.puzzle_container);
 }


};

Puzzle.makeGuess = function ( _guess ) {
 console.log('trying... ' + _guess);

 Guesses.addGuess(_guess);
 WordMask.updateWordMask();

 if (RegExp(_guess, 'i').test(this.lang2)) {
  this.hits++;
 } else {
  this.misses++;
  PuzzleImage.setStage(this.misses);
 }

 console.log(this);

 if (WordMask.getWordMask() == Puzzle.getLang2()) {
  XHR.updateScore(this.puzzleid, this.hits/(this.hits+this.misses));
  // then the puzzle has been solved. report stats here?
  console.log('puzzle finished!');
  console.log('knowledge: ' + this.hits/(this.hits+this.misses));
 }

};

Puzzle.setPuzzle = function ( _id, _lang1, _lang2 ) {

 Puzzle.init();

 this.puzzleid = _id;

 this.lang1 = _lang1;
 this.lang2 = _lang2;

 WordMask.updateWordMask();

 Hint.setHint(this.lang1);

};

window.onload = function () {
 Notify.init();
 Puzzle.init();
 
};

